/*
 * Copyright 2006-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.martinimix.beans.bind;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.config.BeanPostProcessor;

import com.bluemartini.dna.BusinessObjectArray;

/**
 * Provides an abstract binding service implementation.
 * 
 * @author Scott Rossillo
 *
 */
public abstract class AbstractBindingService 
		implements BindingService, BeanNameAware, BeanPostProcessor {
	
	private boolean defaultBindingService = false;
	
	/**
	 * Creates an new binding service instance.
	 */
	public AbstractBindingService() { }

	/* (non-Javadoc)
	 * @see net.martinimix.dao.bind.BindingService#bindBeans(com.bluemartini.dna.BusinessObjectArray, java.lang.Object)
	 */
	public List bindBeans(BusinessObjectArray source, Object target) {

		List beans = new ArrayList(source.size());

		try {
			for(int i = 0; i < source.size(); i++) {
				beans.add(this.bindBean(source.elementAt(i), target.getClass().newInstance()));
			}
		} catch (InstantiationException e) {
			throw new IllegalArgumentException(
					"Target bean [" + target.getClass() + "] must provide a empty public constructor");
		} catch (IllegalAccessException e) {
			throw new IllegalArgumentException(
					"Target bean [" + target.getClass() + "] must provide a empty public constructor");
		}

		return beans;
	}

	/* (non-Javadoc)
	 * @see net.martinimix.dao.bind.BindingService#bindBusinessObjects(java.util.List, java.lang.String)
	 */
	public BusinessObjectArray bindBusinessObjects(List source, String type)
			throws BusinessObjectBindException {
		
		BusinessObjectArray boArray = new BusinessObjectArray(source.size());
		
		for(int i = 0; i < source.size(); i++) {
			boArray.addElementRef(this.bindBusinessObject(source.get(i), type));
		}
		
		return boArray;
	}
	
	/**
	 * Returns true if this bean is the default binding service in its
	 * container.
	 * 
	 * @return
	 */
	private boolean isDefaultBindingService() {
		return defaultBindingService;
	}

	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.BeanNameAware#setBeanName(java.lang.String)
	 */
	public final void setBeanName(String beanName) {
		
		this.defaultBindingService = beanName.equals("bindingService");
	}
	
	/**
	 * Sets this as the binding service on all binding service aware beans.
	 *  
	 * @see BindingServiceAware
	 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
	 */
	public final Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
	
		if(!this.isDefaultBindingService()) {
			return bean;
		}
		
		if(BindingServiceAware.class.isAssignableFrom(bean.getClass())) {
			( (BindingServiceAware) bean ).setBindingService(this);
		}
		
		return bean;
	}

	/**
	 * Returns the given bean, unmodified.
	 * 
	 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
	 */
	public Object postProcessAfterInitialization(Object bean, String name)
			throws BeansException {
		return bean;
	}

}
